import asyncore
import socket,time

import store
import os
import sys
from utils import cdb_debug

DATA_STORE = None

class cdb_server_instance(asyncore.dispatcher):
	def create_buffer(self):
		if not 'inbuffer' in self.__dict__:
			self.inbuffer = ''
		if not 'outbuffer' in self.__dict__:
			self.outbuffer = ''

	def handle_read(self):
		self.create_buffer()
		self.inbuffer += self.recv(1)
		if self.inbuffer.endswith('\n'):
			self.inbuffer = self.inbuffer.strip()
			self.handle_command()
	def handle_command(self):
		cdb_debug('GUEST %s : %s' % (self.getpeername(), self.inbuffer))
		args = self.inbuffer.split(" ")
		if len(args) > 0:
			if args[0] == 'GET':
				self.handle_get(args)
			elif args[0] == 'PUT':
				self.handle_put(args)
			elif args[0] == 'EXIT':
				self.close()
	def handle_get(self, args):
		data = DATA_STORE.get_value(args[1])
		if data != None:
			self.outbuffer = data + '\n'
		else:
			self.outbuffer = 'NO' + '\n'
	def handle_put(self, args):
		DATA_STORE.put_value(args[1], args[2])
		self.outbuffer = 'DONE\n'
	def handle_close(self):
		cdb_debug('Disconnect From %s' % (str(self.getpeername())))
		self.close()
	def writable(self):
		self.create_buffer()
		return (len(self.outbuffer)>0)
	def handle_write(self):
		self.create_buffer()
		sent = self.send(self.outbuffer)
		self.outbuffer = self.outbuffer[sent:]


class cdb_server(asyncore.dispatcher):
	def __init__(self,port = 1010):
		asyncore.dispatcher.__init__(self)
		self.port = port
		self.create_socket(socket.AF_INET,socket.SOCK_STREAM)
		self.bind(("",port))
		self.listen(10)
		cdb_debug('CDB starting...listen at port:'+ str(port) )
		data_dir = 'data'
		max_buckets = 10
		global DATA_STORE
		DATA_STORE = store.CdbStore(data_dir, max_buckets)

	def handle_accept(self):
		channel, addr = self.accept()
		cdb_server_instance(channel)
	
	def clean(self):
		self.close()
		global DATA_STORE
		DATA_STORE.close_all()



if __name__== '__main__':
	try:
		s = cdb_server()
		asyncore.loop()
	except KeyboardInterrupt:
		s.clean()
